package com.cq.hd.common.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.springframework.util.DigestUtils;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class StringUtils {
    private static final String CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

    /**
     * 获取指定长度随机字符串
     *
     * @param length
     * @return
     */
    public static String getRandomString(int length) {
        StringBuffer sb = new StringBuffer();
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            sb.append(CHARS.charAt(random.nextInt(CHARS.length())));
        }
        return sb.toString();
    }

    /**
     * 获取随机数字字符串
     *
     * @param length
     * @return
     */
    public static String getRandomNumString(int length) {
        if (length <= 0) {
            return "";
        }

        char[] numbersAndLetters = ("0123456789").toCharArray();
        Random random = new Random();
        char[] randomStr = new char[length];
        for (int i = 0; i < length; i++) {
            randomStr[i] = numbersAndLetters[random.nextInt(numbersAndLetters.length)];
        }
        return String.valueOf(randomStr);

    }

    /**
     * 获取指定区间随机数，
     *
     * @param down 下限 ，包含
     * @param up   上限 ，包含
     **/
    public static int getRandomNum(int down, int up) {
        return (int) (down + Math.random() * (up - down + 1));
    }

    /**
     * 功能：获取指定范围内N个不重复的数
     *
     * @param min 指定范围最小值，包含
     * @param max 指定范围最大值，不包含
     * @param n   随机数个数
     */
    public static int[] getRandomNumNoRepeat(int min, int max, int n) {
        Set<Integer> set = new HashSet<Integer>();
        int[] array = new int[n];
        for (; true; ) {
            // 调用Math.random()方法
            int num = (int) (Math.random() * (max - min)) + min;

            // 将不同的数存入HashSet中
            set.add(num);
            // 如果存入的数小于指定生成的个数，则调用递归再生成剩余个数的随机数，如此循环，直到达到指定大小
            if (set.size() >= n) {
                break;
            }
        }
        int i = 0;
        for (int a : set) {
            array[i] = a;
            i++;
        }
        return array;
    }


    /**
     * 生成Salt
     *
     * @return
     */
    public static String generateSalt() {
        return getRandomString(8);
    }


    /**
     * SHA1
     *
     * @param text
     * @return
     */
    public static String SHA1(String text) {
        try {
            MessageDigest digest = MessageDigest
                    .getInstance("SHA-1");
            digest.update(text.getBytes());
            byte messageDigest[] = digest.digest();
            // Create Hex String
            StringBuffer hexString = new StringBuffer();
            // 字节数组转换为 十六进制 数
            for (int i = 0; i < messageDigest.length; i++) {
                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexString.append(0);
                }
                hexString.append(shaHex);
            }
            return hexString.toString();

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return "";
    }


    /**
     * 判断字符串是否为空
     *
     * @param string
     * @return
     */
    public static boolean isNullOrEmpty(String string) {
        return string == null || "".equals(string);
    }

    /**
     * 字符串组
     *
     * @param groups
     * @return
     */
    public static String groupString(String groups) {
        if (groups == null) {
            return "";
        }
        return "," + groups.replaceAll("^,|,$", "") + ",";
    }

    /**
     * 获取非空字符串
     */
    public static String firstNotNull(String... strings) {
        for (String string : strings) {
            if (!isNullOrEmpty(string)) {
                return string;
            }
        }
        return "";
    }

    /**
     * 获取首字母
     */
    public static String getInitial(String string) {
        if (isNullOrEmpty(string)) {
            return "#";
        }
        String initial = string.substring(0, 1).toUpperCase();
        if (!initial.matches("[A-Z]")) {
            initial = "#";
        }
        return initial;
    }

    /**
     * 获取基本文件名
     *
     * @param path
     * @return
     */
    public static String getBaseFileName(String path) {
        int pos = path.lastIndexOf("/");
        if (pos > -1) {
            path = path.substring(pos + 1);
        }
        pos = path.lastIndexOf(".");
        if (pos > -1) {
            path = path.substring(0, pos);
        }
        return path;
    }


    /**
     * 转码
     *
     * @param str
     * @return
     */
    public static String TextDecode(String str) {

        if (str != null && !Charset.forName("GBK").newEncoder().canEncode(str)) {

            try {
                str = new String(str.getBytes("ISO-8859-1"), "utf-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }

        return str;
    }

    /**
     * 转码
     *
     * @param str
     * @return
     */
    public static String UrlDecode(String str) {
        return TextDecode(str);
    }


    /**
     * 距离文本
     *
     * @param distance
     * @return
     */
    public static String getDistanceText(long distance) {
        if (distance < 20) {
            return "20m以内";
        } else if (distance < 1000) {
            return distance + "m";
        } else {
            return ((double) Math.round((double) distance / 100)) / 10 + "km";
        }
    }

    /**
     * 获取性别名称
     *
     * @param gender
     * @return
     */
    public static String getGenderText(int gender) {
        if (gender == 1) {
            return "男";
        } else {
            return "女";
        }
    }

    /**
     * 字符串截取
     *
     * @param text
     * @param len
     * @return
     */
    public static String substr(String text, int len) {
        if (text.length() > len) {
            text = text.substring(0, len - 2) + "...";
        }
        return text;
    }

    /**
     * 格式化数据
     *
     * @param number
     * @param length
     * @param prefix
     * @return
     */
    public static String formatNumber(Number number, Integer length, String prefix) {

        if (number == null) {
            return "";
        }
        long no = number.longValue();
        int len = length == null ? 3 : length;

        double max = Math.pow(10D, (double) len);
        String result = String.valueOf(no);
        if (no < max) {
            no = (long) (max + no);
            result = String.valueOf(no);
            result = result.substring(result.length() - len);
        }
        if (prefix != null) {
            result = prefix + result;
        }
        return result;
    }

    /**
     * 格式化数据
     *
     * @param number
     * @param length
     * @return
     */
    public static String formatNumber(Number number, Integer length) {
        return formatNumber(number, length, null);
    }

    /**
     * 数字字符串
     *
     * @param string
     * @return
     */
    public static boolean isNumeric(String string) {
        return isNotBlank(string) && string.matches("\\d*");
    }

    /**
     * 是否是商户编号
     */
    public static boolean isMerchantNo(String string) {
        return isNotBlank(string) && string.matches("^M\\d{15}$");
    }

    /**
     * 是否是商家编号
     */
    public static boolean isBusinessNo(String string) {
        return isNotBlank(string) && string.matches("^B\\d{15}$");
    }

    /**
     * 是否是经纪人邀请码
     */
    public static boolean isUserInviteCode(String string) {
        return isNotBlank(string) && string.matches("^U[0-9A-Z]{9}$");
    }

    /**
     * 列表转字符串数组
     *
     * @param list
     * @return
     */
    public static final <E> String[] toStrings(List<E> list) {
        String[] items = new String[list.size()];
        for (int i = 0; i < list.size(); i++) {
            items[i] = JSONObject.toJSONString(list.get(i));
        }
        return items;
    }

    public static final String toString(Object o) {
        return JSONObject.toJSONString(o);
    }

    /**
     * 转long
     */
    public static long toLong(Object object) {
        return toLong(object, 0);
    }

    /**
     * 转long
     *
     * @param object 要转换的对象
     * @param values 默认值
     */
    public static long toLong(Object object, long values) {
        try {
            return Long.parseLong(object.toString());
        } catch (Exception ex) {
            return values;
        }
    }

    /**
     * 转int
     */
    public static int toInt(Object object) {
        return toInt(object, 0);
    }

    /**
     * 转int
     *
     * @param object 要转换的对象
     * @param values 默认值
     */
    public static int toInt(Object object, int values) {
        try {
            return Integer.parseInt(object.toString());
        } catch (Exception ex) {
            return values;
        }
    }

    /**
     * 转BigDecimal
     */
    public static BigDecimal toBigDecimal(Object object) {
        return toBigDecimal(object, 0, new BigDecimal(0));
    }

    /**
     * 转BigDecimal
     *
     * @param object   要转换的对象
     * @param newScale 小数点位数
     */
    public static BigDecimal toBigDecimal(Object object, int newScale) {
        return toBigDecimal(object, newScale, new BigDecimal(0));
    }

    /**
     * 转BigDecimal
     *
     * @param object   要转换的对象
     * @param values   默认值
     * @param newScale 小数点位数
     */
    public static BigDecimal toBigDecimal(Object object, int newScale, BigDecimal values) {
        try {
            //数字字符串
            String StrBd = object.toString();
            //构造以字符串内容为值的BigDecimal类型的变量bd
            BigDecimal bd = new BigDecimal(StrBd);
            //设置小数位数，第一个变量是小数位数，第二个变量是取舍方法(四舍五入)
            bd = bd.setScale(newScale, BigDecimal.ROUND_HALF_UP);
            return bd;
        } catch (Exception ex) {
            return values;
        }
    }


    /**
     * 拼接字符串
     *
     * @param list
     * @param separator
     * @return
     */
    public static final String join(List<String> list, String separator) {
        StringBuffer stringBuffer = new StringBuffer();
        for (String str : list) {
            stringBuffer.append(str);
            stringBuffer.append(separator);
        }
        String result = stringBuffer.toString();
        if (!"".equals(separator)) {
            result = result.replaceAll(separator + "$", "");
        }
        return result;
    }

    /**
     * 字符串转对象
     *
     * @param value
     * @param type
     * @return
     */
    public static final Object toObject(String value, String type) {
        if ("int".equalsIgnoreCase(type)) {
            return Integer.valueOf(value);
        } else if ("long".equalsIgnoreCase(type)) {
            return Long.valueOf(value);
        } else if ("float".equalsIgnoreCase(type)) {
            return Float.valueOf(value);
        } else if ("double".equalsIgnoreCase(type)) {
            return Double.valueOf(value);
        } else if ("boolean".equalsIgnoreCase(type)) {
            return Boolean.valueOf(value);
        } else if ("json".equalsIgnoreCase(type)) {
            return JSONObject.parse(value);
        } else if ("array".equalsIgnoreCase(type)) {
            return JSONArray.parse(value);
        } else if ("decimal".equalsIgnoreCase(value)) {
            return new BigDecimal(value);
        }
        return value;
    }

    /**
     * 字符串转
     *
     * @param str
     * @param regex
     * @return
     */
    public static final List<String> split(String str, String regex) {
        if (isNullOrEmpty(str)) {
            return new ArrayList<String>();
        }
        String[] array = str.split(regex);
        return Arrays.asList(array);
    }

    /**
     * 字符串转列表
     *
     * @param str
     * @param regex
     * @return
     */
    public static final List<Integer> split2Ingeter(String str, String regex) {
        List<Integer> items = new ArrayList<Integer>();
        if (!isNullOrEmpty(str)) {
            String[] array = str.split(regex);
            for (String string : array) {
                items.add(Integer.valueOf(string));
            }
        }
        return items;
    }

    /**
     * 生成唯一字符串
     *
     * @param prev
     * @return
     */
    public static String uniqueNo(String prev) {
        return prev + LocalDateUtil.toLocalDateTimeToString(LocalDateUtil.getNowLocalDateTime(), "yyyyMMddHHmmssSSS") + StringUtils.getRandomNumString(3);
    }

    /**
     * 手机号加密
     *
     * @param phone
     * @return
     */
    public static String encodePhone(String phone) {
        return phone.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
    }

    /**
     * 判断是否是手机号
     *
     * @param phone
     * @return
     */
    public static boolean isPhoneNo(String phone) {
        String telRegex = "^1[34578]\\d{9}";
        // "^1"代表第1位为数字1，"[34578]"代表第二位可以为3、5、8中的一个，"\\d{9}"代表后面是可以是0～9的数字，有9位。
        if (isNullOrEmpty(phone)) {
            return false;
        } else {
            return phone.matches(telRegex);
        }
    }

    /**
     * 校验密码格式
     *
     * @param password
     * @return
     */
    public static boolean isPassword(String password) {
        String regex = "[A-Za-z0-9]{6,22}$";
        if (isNullOrEmpty(password)) {
            return false;
        } else {
            return password.matches(regex);
        }
    }

    /**
     * @param origin:要加密的原文
     * @param encode:编码格式，默认utf-8
     * @return 返回加密结果
     * @Title: MD5加密
     * @Description: MD5加密
     */
    public static String MD5(String origin, String encode) {
        if (encode == null || encode.length() == 0) {
            encode = "UTF-8";
        }
        String result = null;
        //对密码进行 md5 加密
        result = DigestUtils.md5DigestAsHex(origin.getBytes(Charset.forName(encode)));
        return result;
    }

    /**
     * sql防注入，将sql值 单引号替换成2个单引号
     *
     * @param sql
     * @return
     */
    public static String replaceSql(String sql) {
        if (sql != null && sql.length() > 0) {
            return sql.replace("'", "''");
        }
        return "";
    }


    /**
     * byte 数组与 long 的相互转换
     **/
    public static long bytesToLong(byte[] bytes) {
        ByteBuffer buffer = ByteBuffer.wrap(bytes, 0, bytes.length);
        return buffer.getLong();
    }

    /**
     * 字符串转成 byte 数组  UTF_8编码
     **/
    public static byte[] stringToBytes(String x) {
        if (x == null || x.length() == 0) {
            return null;
        }
        byte[] utf8 = x.getBytes(StandardCharsets.UTF_8);
        return utf8;
    }

    /**
     * url编码
     **/
    public static String urlEncode(String str) {
        String result = "";
        if (null == str) {
            return "";
        }
        try {
            result = java.net.URLEncoder.encode(str, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * url  Decode 编码
     **/
    public static String urlDecode(String str) {
        String result = "";
        if (null == str) {
            return "";
        }
        try {
            result = java.net.URLDecoder.decode(str, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * base64 Encode 加密
     **/
    public static String base64Encode(String content) {
        final Base64.Encoder encoder = Base64.getEncoder();
        String encodedText = "";
        final byte[] textByte;
        try {
            textByte = content.getBytes("UTF-8");
            encodedText = encoder.encodeToString(textByte);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return encodedText;
    }

    /**
     * base64 Decode 解密
     **/
    public static String base64Decode(String encodedText) {
        final Base64.Decoder decoder = Base64.getDecoder();
        String decodedText = "";

        final byte[] textByte;
        try {
            //解码
            decodedText = new String(decoder.decode(encodedText), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return decodedText;
    }

    /**
     * 过滤html标签，提取文本
     *
     * @param inputString
     * @return
     */
    public static String Html2Text(String inputString) {
        String htmlStr = inputString; //含html标签的字符串
        String textStr = "";
        Pattern p_script;
        Matcher m_script;
        Pattern p_style;
        Matcher m_style;
        Pattern p_html;
        Matcher m_html;
        try {
            String regEx_script = "<[\\s]*?script[^>]*?>[\\s\\S]*?<[\\s]*?\\/[\\s]*?script[\\s]*?>"; //定义script的正则表达式{或<script[^>]*?>[\\s\\S]*?<\\/script> }
            String regEx_style = "<[\\s]*?style[^>]*?>[\\s\\S]*?<[\\s]*?\\/[\\s]*?style[\\s]*?>"; //定义style的正则表达式{或<style[^>]*?>[\\s\\S]*?<\\/style> }
            String regEx_html = "<[^>]+>"; //定义HTML标签的正则表达式
            p_script = Pattern.compile(regEx_script, Pattern.CASE_INSENSITIVE);
            m_script = p_script.matcher(htmlStr);
            htmlStr = m_script.replaceAll(""); //过滤script标签
            p_style = Pattern.compile(regEx_style, Pattern.CASE_INSENSITIVE);
            m_style = p_style.matcher(htmlStr);
            htmlStr = m_style.replaceAll(""); //过滤style标签
            p_html = Pattern.compile(regEx_html, Pattern.CASE_INSENSITIVE);
            m_html = p_html.matcher(htmlStr);
            htmlStr = m_html.replaceAll(""); //过滤html标签
            textStr = htmlStr;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return textStr;//返回文本字符串
    }


    /**
     * 根据换行符拆分字符串
     *
     * @param * @param null
     * @return
     * @author gaobaozong
     * @date Created in 2020/6/29 - 上午10:46
     */
    public static String[] splitByLineSeparator(String str) {
        if (isBlank(str)) {
            return null;
        }

        String regex = "\n";
        int i = str.indexOf(regex);
        if (i == 0) {
            regex = "\r\n";
            i = str.indexOf(regex);
            if (i == 0) {
                regex = "\r";
                i = str.indexOf(regex);
            }
        }
        return str.split(regex);
    }

    public static boolean isBlank(String str) {
        return org.apache.commons.lang3.StringUtils.isBlank(str);
    }

    public static boolean isNotBlank(String str) {
        return !isBlank(str);
    }

    /**
     * 字符切割,如:30=50  -3=3|-1=1
     * <br/>
     *
     * @param str
     * @return java.util.List<java.lang.Long>
     * @author mYunYu
     * @create 2020-08-10 11:14
     */
    public static List<Long> splitStr(String str) {
        List<Long> stringList = new ArrayList<>();
        if (str.contains("|")) {
            String[] split = str.split("\\|");
            String splitStr = split[0];
            String splitS = split[1];
            if (splitStr.contains("=")) {
                String[] split1 = splitStr.split("=");
                String[] split2 = splitS.split("=");
                String splitStrOne = split1[0];
                String splitStrTwo = split1[1];

                String splitStrThree = split2[0];
                if (split2.length == 2) {
                    String splitStrFour = split2[1];
                    stringList.add(Long.valueOf(splitStrFour));
                }

                stringList.add(Long.valueOf(splitStrOne));
                stringList.add(Long.valueOf(splitStrTwo));
                stringList.add(Long.valueOf(splitStrThree));
            } else {
                stringList.add(Long.valueOf(splitStr));
                stringList.add(Long.valueOf(splitS));
            }
        } else if (str.contains("=")) {
            String[] split1 = str.split("=");
            String splitStrOne = split1[0];
            String splitStrTwo = split1[1];

            stringList.add(Long.valueOf(splitStrOne));
            stringList.add(Long.valueOf(splitStrTwo));
        }
        return stringList;
    }

    /**
     * @description: 提取字符串中的所有url
     * @author: Kyrie.li
     * @date: 2020/12/8 10:09
     * @param:
     * @return:
     */
    public static String filterSpecialStr(String regex, String partition, String data) {
        // sb存放正则匹配的结果
        StringBuilder sb = new StringBuilder();
        // 编译正则字符串
        Pattern p = Pattern.compile(regex);
        // 利用正则去匹配
        Matcher matcher = p.matcher(data);
        // 如果找到了我们正则里要的东西
        while (matcher.find()) {
            sb.append(matcher.group()).append(partition);
        }
        return sb.toString();
    }


    public static String getParamByUrl(String url, String name) {
        url += "&";
        String pattern = "(\\?|&){1}#{0,1}" + name + "=[a-zA-Z0-9]*(&{1})";
        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(url);
        if (m.find()) {
            return m.group(0).split("=")[1].replace("&", "");
        } else {
            return null;
        }
    }
}
